package se.webbzon.boltzmann.editor.component.geometry;

import java.awt.GridLayout;
import java.awt.event.ActionEvent;

import javax.swing.AbstractAction;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTextField;

import se.webbzon.boltzmann.editor.component.AbstractComponent;
import se.webbzon.boltzmann.object.geometry.GeometryEnum;

public class GeometryPanel extends AbstractComponent {
	
	// Auto generated serial version UID
	private static final long serialVersionUID = 48762976113419799L;

	// The selected geometry in this panel
	private GeometryEnum selectedGeometry;
	
	// The button group of this panel
	private final ButtonGroup geometry;
	
	// The radio buttons of this panel
	private final JRadioButton	cone, cube, cylinder, ellipsoid, floor, wall,
								xyplane, xzplane, yzplane;
	
	// The surface check box of this panel
	private final JCheckBox	open, backfaced;
	
	// The division input of this panel
	private final JTextField divisions;
	
	/*============================================================
	Constructors
	============================================================*/
	
	public GeometryPanel(GeometryEnum geometry, boolean open, int divisions) {
		this(false,geometry,open,divisions,false);
	}
	
	public GeometryPanel(GeometryEnum geometry, boolean open, int divisions, boolean backfaced) {
		this(true,geometry,open,divisions,backfaced);
	}
	
	private GeometryPanel(boolean appearance, GeometryEnum geometry, boolean open, int divisions, boolean backfaced) {
		super("Geometry");
		this.selectedGeometry = geometry;
		setLayout(new BoxLayout(this,BoxLayout.Y_AXIS));
		
		JPanel geometryPanel = new JPanel();
		geometryPanel.setLayout(new GridLayout(3,3));
		geometryPanel.setBorder(BorderFactory.createTitledBorder("Geometry"));
		
		this.geometry = new ButtonGroup();
		cone = new JRadioButton(new GeometryAction("Cone",GeometryEnum.CONE));
		cube = new JRadioButton(new GeometryAction("Cube",GeometryEnum.CUBE));
		cylinder = new JRadioButton(new GeometryAction("Cylinder",GeometryEnum.CYLINDER));
		ellipsoid = new JRadioButton(new GeometryAction("Ellipsoid",GeometryEnum.ELLIPSOID));
		floor = new JRadioButton(new GeometryAction("Floor",GeometryEnum.FLOOR));
		wall = new JRadioButton(new GeometryAction("Wall",GeometryEnum.WALL));
		xyplane = new JRadioButton(new GeometryAction("XY-Plane",GeometryEnum.XYPLANE));
		xzplane = new JRadioButton(new GeometryAction("XZ-Plane",GeometryEnum.XZPLANE));
		yzplane = new JRadioButton(new GeometryAction("YZ-Plane",GeometryEnum.YZPLANE));
		this.geometry.add(cone);
		this.geometry.add(cube);
		this.geometry.add(cylinder);
		this.geometry.add(ellipsoid);
		this.geometry.add(floor);
		this.geometry.add(wall);
		this.geometry.add(xyplane);
		this.geometry.add(xzplane);
		this.geometry.add(yzplane);
		geometryPanel.add(cone);
		geometryPanel.add(cube);
		geometryPanel.add(cylinder);
		geometryPanel.add(ellipsoid);
		geometryPanel.add(floor);
		geometryPanel.add(wall);
		geometryPanel.add(xyplane);
		geometryPanel.add(xzplane);
		geometryPanel.add(yzplane);
		selectGeometry(geometry);
		
		add(geometryPanel);
		
		JPanel settingsPanel = new JPanel();
		settingsPanel.setLayout(new GridLayout(2,appearance ? 3 : 2));
		settingsPanel.setBorder(BorderFactory.createTitledBorder("Geometry Settings"));
		settingsPanel.add(new JLabel("Divisions:"));
		settingsPanel.add(new JLabel("Open surface:"));
		if (appearance)
			settingsPanel.add(new JLabel("Backfaced:"));
		this.divisions = new JTextField("" + divisions);
		this.open = new JCheckBox();
		this.open.setSelected(open);
		settingsPanel.add(this.divisions);
		settingsPanel.add(this.open);
		if (appearance) {
			this.backfaced = new JCheckBox();
			this.backfaced.setSelected(backfaced);
			settingsPanel.add(this.backfaced);
		} else
			this.backfaced = null;
		geometryPanel.add(settingsPanel);
		
		add(settingsPanel);
	}
	
	/*============================================================
	Public Methods
	============================================================*/
	
	/** Returns the selected geometry in this panel. **/
	public GeometryEnum getGeometry() {
		return selectedGeometry;
	}
	
	/** Returns true if the surface of the geometry is selected to
	 * be open in this panel. **/
	public boolean isOpen() {
		return open.isSelected();
	}
	
	/** Returns the number of divisions selected in this panel. **/
	public int getDivisions() throws NumberFormatException {
		return Integer.parseInt(divisions.getText());
	}
	
	/** Returns true if the surface of the geometry is selected to
	 * be back-faced in this panel. This property is only available
	 * is this geometry panel modifies an appearance. **/
	public boolean isBackfaced() {
		if (this.backfaced == null)
			return false;
		else
			return backfaced.isSelected();
	}
	
	/*============================================================
	Private Methods
	============================================================*/
	
	/** Selects the geometry radio button by using the given geometry
	 * enumeration type. **/
	private void selectGeometry(GeometryEnum geometry) {
		switch (geometry) {
		case CONE: this.geometry.setSelected(cone.getModel(), true); break;
		case CUBE: this.geometry.setSelected(cube.getModel(), true); break;
		case CYLINDER: this.geometry.setSelected(cylinder.getModel(), true); break;
		case ELLIPSOID: this.geometry.setSelected(ellipsoid.getModel(), true); break;
		case FLOOR: this.geometry.setSelected(floor.getModel(), true); break;
		case WALL: this.geometry.setSelected(wall.getModel(), true); break;
		case XYPLANE: this.geometry.setSelected(xyplane.getModel(), true); break;
		case XZPLANE: this.geometry.setSelected(xzplane.getModel(), true); break;
		case YZPLANE: this.geometry.setSelected(yzplane.getModel(), true); break;
		}
	}
	
	/*============================================================
	Private Classes
	============================================================*/
	
	/** An implementation of an abstract action used for the geometry radio buttons. **/
	private final class GeometryAction extends AbstractAction {
		
		// Auto generated serial version UID
		private static final long serialVersionUID = 5572529139243012044L;

		// The geometry associated with this action
		private final GeometryEnum geometry;
		
		public GeometryAction(String name, GeometryEnum geometry) {
			this.geometry = geometry;
			putValue(AbstractAction.NAME,name);
		}

		@Override public void actionPerformed(ActionEvent event) {
			selectedGeometry = geometry;
		}
		
	}

}
